package org.teamswift.crow.rbac.cmd;

import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
import org.teamswift.crow.rbac.dto.CrowAuthorizeDto;
import org.teamswift.crow.rbac.entity.CrowPermissionResource;
import org.teamswift.crow.rbac.entity.CrowRole;
import org.teamswift.crow.rbac.entity.CrowUser;
import org.teamswift.crow.rbac.enums.CrowResourceActions;
import org.teamswift.crow.rbac.enums.CrowRowPermissionLevel;
import org.teamswift.crow.rbac.repository.CrowRoleRepository;
import org.teamswift.crow.rbac.service.CrowPermissionResourceService;
import org.teamswift.crow.rbac.service.CrowRoleService;
import org.teamswift.crow.rbac.service.CrowUserService;
import org.teamswift.crow.rest.exception.impl.DataNotFoundException;

import javax.validation.constraints.NotNull;
import java.util.*;

@ShellComponent
public class AuthorizeSuperUser {

    private final CrowUserService crowUserService;

    private final CrowRoleRepository crowRoleRepository;

    private final CrowRoleService crowRoleService;

    private final CrowPermissionResourceService crowPermissionResourceService;

    public AuthorizeSuperUser(CrowUserService crowUserService, CrowRoleRepository crowRoleRepository, CrowRoleService crowRoleService, CrowPermissionResourceService crowPermissionResourceService) {
        this.crowUserService = crowUserService;
        this.crowRoleRepository = crowRoleRepository;
        this.crowRoleService = crowRoleService;
        this.crowPermissionResourceService = crowPermissionResourceService;
    }

    @ShellMethod(
            group = "Crow"
    )
    public void authorizeSu(
            @NotNull
            String mobile
    ) {
        CrowUser crowUser = crowUserService.findOneByMobile(mobile).orElseThrow(() -> {
            throw new DataNotFoundException(
                    "can't find user via mobile: " + mobile
            );
        });

        CrowRole role = crowRoleRepository.findByOrganizationIdAndName(
                crowUser.getOrganizationId(),
                "su"
        ).orElseGet(() -> {
            System.out.println("The role named `su` can't be found, create it first.");
            CrowRole crowRole = new CrowRole();
            crowRole.setName("su");
            crowRole.setOrganizationId(crowUser.getOrganizationId());
            crowRole.setDescription("Auto generated super user role");
            return crowRoleRepository.save(crowRole);
        });

        crowUserService.assignRole(crowUser, role);

        Set<CrowPermissionResource> nodes = crowPermissionResourceService.getAllNodes();
        List<CrowAuthorizeDto> perms = new ArrayList<>();

        nodes.forEach(node -> {
            CrowAuthorizeDto dto = new CrowAuthorizeDto();
            dto.setAction(CrowResourceActions.MANAGE.name());
            dto.setPermissionResource(node.getId());
            dto.setRowPermissionLevel(CrowRowPermissionLevel.All);

            perms.add(dto);
        });

        crowRoleService.authorize(role, perms);

        System.out.println("done.");
    }

}
